#pragma once

#include "sock.hpp"
#include <functional>
#include<pthread.h>

namespace Http
{
    using func_t = std::function<std::string(std::string &)>;
    class HttpServer;
    class ThreadData
    {
    public:
        ThreadData(int sock, const std::string &ip, const uint16_t &port, HttpServer *tsvrp)
            : _sock(sock), _ip(ip), _port(port), _tsvrp(tsvrp)
        {
        }

    public:
        int _sock;
        std::string _ip;
        uint16_t _port;
        HttpServer *_tsvrp; // 指向TCP服务器
    };

    class HttpServer
    {
    public:
        HttpServer(func_t func, uint16_t port)
            : _func(func), _port(port)
        {
        }
        void InitServer()
        {
            _listensock.Socket();
            _listensock.Bind(_port);
            _listensock.Listen();
        }
        //处理http请求
        void Request(int sock)
        {
            char buffer[4096];
            std::string request;
            //TCP是面向字节流的，有可能一次会读不完，但这次我们假定它可以一次读完
            ssize_t s = recv(sock,buffer,sizeof(buffer)-1,0);
            if(s>0)
            {
                buffer[s]=0;
                request = buffer;
                //func处理request请求，返回一个response响应
                std::string response = _func(request);
                send(sock,response.c_str(),response.size(),0);
            }
            else
            {
                std::cerr<<"client quit\n";
            }
        }
        void Start()
        {
            while(true)
            {
                std::string clientip;
                uint16_t clientport;
                int sock = _listensock.Accept(&clientip,&clientport);
                if(sock<0)
                {
                    continue;
                }
                pthread_t tid;
                ThreadData *td=new ThreadData(sock,clientip,clientport,this);
                pthread_create(&tid,nullptr,ThreadRoutine,td);
            }
        }
        static void* ThreadRoutine(void* args)
        {
            pthread_detach(pthread_self());
            ThreadData *td=static_cast<ThreadData*>(args);
            td->_tsvrp->Request(td->_sock);
            close(td->_sock);
            delete td;
            return nullptr;
        }
    private:
        Http::Sock _listensock;
        uint16_t _port;
        func_t _func;
    };
}